package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.wemedia.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
import io.minio.messages.Item;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl implements WmNewsService {
    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    public ResponseResult list(WmNewsPageReqDto wmNewsPageReqDto) {

        //1.检查参数
        wmNewsPageReqDto.checkParam();

        Integer userId = WmThreadLocalUtil.getUser().getId();

        LambdaQueryWrapper<WmNews> wrapper = Wrappers.lambdaQuery(WmNews.class);
        //状态精确查询
        if (wmNewsPageReqDto.getStatus()!=null){
            wrapper.eq(WmNews::getStatus,wmNewsPageReqDto.getStatus());
        }

        //频道精确查询
        if (wmNewsPageReqDto.getChannelId()!=null){
            wrapper.eq(WmNews::getChannelId,wmNewsPageReqDto.getChannelId());
        }

        //时间范围查询
        if (wmNewsPageReqDto.getBeginPubdate()!=null&&wmNewsPageReqDto.getEndPubdate()!=null){
            wrapper.between(WmNews::getPublishTime,wmNewsPageReqDto.getBeginPubdate(),wmNewsPageReqDto.getEndPubdate());
        }

        //关键字模糊查询
        if(StringUtils.isNoneBlank(wmNewsPageReqDto.getKeyword())){
            wrapper.like(WmNews::getTitle,wmNewsPageReqDto.getKeyword());
        }

        //查询是用户发布的文章
        wrapper.eq(WmNews::getUserId,userId);
        wrapper.orderByDesc(WmNews::getPublishTime);

        Page page = wmNewsMapper.selectPage(new Page(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize()), wrapper);
        ResponseResult responseResult=new PageResponseResult(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize(), (int) page.getTotal());
        responseResult.setData(page.getRecords());
        return responseResult;
    }

    @Override
    public ResponseResult submit(WmNewsDto wmNewsDto) {
        //1. 参数校验
        if (StringUtils.isBlank(wmNewsDto.getTitle())||StringUtils.isBlank(wmNewsDto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2. 封装数据
        WmNews wmNews = new WmNews();
        //批量复制数据到目标对象 (属性名称和类型完成一致)  type : 布局类型    images : 封面图片
        BeanUtils.copyProperties(wmNewsDto,wmNews);

        //2.1 抽取内容中的图片
        String content = wmNews.getContent();
        List<Map> maps = JSON.parseArray(content, Map.class);
        List<String> contentImages = maps.stream().filter(item -> "image".equals(item.get("type"))).map(item -> item.get("value").toString()).collect(Collectors.toList());

        //2.2 抽取封面图片
        List<String> coverImages = wmNewsDto.getImages();

        //2.3 封装type数据
        if (wmNewsDto.getType()!=null&&wmNewsDto.getType()==-1){
            if (contentImages.size()>=3){
                wmNews.setType((short) 3);
                coverImages=contentImages.stream().limit(3).collect(Collectors.toList());
            }else if (contentImages.size()>0){
                wmNews.setType((short) 1);
                coverImages=contentImages.stream().limit(1).collect(Collectors.toList());
            }else {
                wmNews.setType((short) 0);
            }
        }

        //2.4 封装封面图片数据
        if (coverImages.size()>0){
            wmNews.setImages(StringUtils.join(coverImages,","));
        }

        //3. 保存文章数据  新增  修改
        saveOrUpdate(wmNews);

        //4. 保存素材和文章的关联数据
        //4.1 保存文章和内容素材的引用关系
        saveContentImageRelation(wmNews,contentImages);

        //4.2 保存文章和封面素材的引用关系
        saveCoverImageRelation(wmNews,coverImages);

        wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        return ResponseResult.okResult("发布成功!");
    }

    /**
     * 文章的上架下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        WmNews wmNews = wmNewsMapper.selectById(dto.getId());
        if (wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        if (wmNews.getStatus()!=WmNews.Status.PUBLISHED.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"未发布的文章无法上下架");
        }

        //3. 修改文章配置信息
        if(dto.getEnable()!=0&&dto.getEnable()!=1){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        wmNews.setEnable(dto.getEnable());
        wmNewsMapper.updateById(wmNews);

        //4. 向kafka发送消息  文章id , 状态
        Map<String,String> map=new HashMap();
        map.put("articleId",wmNews.getArticleId().toString());
        map.put("enable",wmNews.getEnable().toString());

        kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));
        return ResponseResult.okResult("文章上下架成功");
    }

    /**
     * 保存文章和内容素材的引用关系
     *
     * @param wmNews
     * @param contentImages
     */
    private void saveContentImageRelation(WmNews wmNews, List<String> contentImages) {
        if (CollectionUtils.isEmpty(contentImages)) {
            return;
        }
        saveImageRelation(wmNews, contentImages, (short) 0);
    }

    /**
     * 保存文章和封面素材的引用关系
     *
     * @param wmNews
     * @param contentImages
     */
    private void saveCoverImageRelation(WmNews wmNews, List<String> contentImages) {
        if (CollectionUtils.isEmpty(contentImages)) {
            return;
        }
        saveImageRelation(wmNews, contentImages, (short) 1);
    }



    /**
     * 保存文章和素材的关联关系
     *
     * @param wmNews
     * @param images 素材URL集合
     * @param type   引用类型 0: 内容引用  1 : 主图引用
     */
    private void saveImageRelation(WmNews wmNews, List<String> images, short type) {
        //如果是草稿不需要保存关联关系
        if (wmNews.getStatus()==0){
            return;
        }

        //1. 根据URL获取素材ID
        images = images.stream().distinct().collect(Collectors.toList());
        LambdaQueryWrapper<WmMaterial> wrapper = Wrappers.lambdaQuery(WmMaterial.class).in(WmMaterial::getUrl, images);
        //1.1 查询素材列表
        List<WmMaterial> materials = wmMaterialMapper.selectList(wrapper);
        //1.2 提取素材ID
        List<Integer> ids = materials.stream().map(material -> material.getId()).collect(Collectors.toList());

        //1.3 判断素材是否缺失
        if (ids.size()!=images.size()) {
            throw new RuntimeException("素材数据丢失");
        }

        //2. 保存关联数据
        wmNewsMaterialMapper.saveImageRelation(wmNews.getId(), ids,type);
    }



    //判断是新增还是修改
    private void saveOrUpdate(WmNews wmNews) {
        //1. id存在修改, id不存在新增
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short) 1);

        if (wmNews.getId()==null){
            wmNews.setCreatedTime(new Date());
            wmNewsMapper.insert(wmNews);
            return;
        }
        wmNewsMapper.updateById(wmNews);
        //修改完数据后删除关系表中的数据
        wmNewsMaterialMapper.delete(Wrappers.lambdaQuery(WmNewsMaterial.class).eq(WmNewsMaterial::getNewsId,wmNews.getId()));
    }
}
